# !/usr/bin/env python
# -*- coding: utf-8 -*-
"""
 -------------------------------------------------
    File Name:     variable_manager.py
    Description:   变量管理模块
 -------------------------------------------------
 """
import json
from string import Template
from typing import Any

from jsonpath import jsonpath

from apitesting.src.enums.var_type import VarEnum
from apitesting.common.util.allure_handler import allure_handler
from apitesting.common.util.logger import log
from apitesting.src.models import ExtractVariableModel

# 缓存字典
cache = {}


class VarsExtractor:

    @staticmethod
    def record_variables(target_obj: dict, model: ExtractVariableModel | str) -> None:
        """
        记录变量

        根据提供的jsonpath从目标字典中提取值，并根据设置类型将提取的值记录为变量。
        变量可以记录到缓存、环境变量或全局变量中。

        :param model: 变量提取模型或字符串格式"name=jsonpath"
        :param target_obj: 目标字典对象
        :return: 无返回值
        """
        # log.debug(f'开始提取变量: {model}')

        # 初始化变量名和JSON路径
        if isinstance(model, ExtractVariableModel):
            name = model.name
            json_path = model.jsonpath
            variable_scope = model.variable_scope
        elif isinstance(model, str):
            name, json_path = [part.strip() for part in model.split('=')]  # 使用split方法分割字符串，并去除空格
            variable_scope = VarEnum.ENV  # 默认为环境变量，因为字符串模式没有提供作用域信息
        else:
            error_msg = f'参数类型错误，请检查参数类型是否正确，当前参数类型：{type(model)}'
            log.error(error_msg)
            raise TypeError(error_msg)

        # log.debug(f'提取变量名: {name}, JSON路径: {json_path}')
        value: list = jsonpath(obj=target_obj, expr=str(json_path))
        # log.info(f'提取到值: {value}')

        # 处理提取结果
        if not value:
            error_msg = f'jsonpath 取值失败, 表达式: {json_path}'
            log.error(error_msg)
            raise Exception(error_msg)
        value_str = value[0] if len(value) == 1 else value
        # 判断取值是不是多个值
        if len(value) > 1:
            log.warning(f'提取到多个值{value}，请检查是否有误。当前只取第一个值，取到的值: {value[0]}')

        # 根据设置类型，将值记录到不同的变量存储中
        if isinstance(model, ExtractVariableModel):
            if model.variable_scope == VarEnum.ENV:
                cache[name] = value_str
        else:
            cache[name] = value_str

        # log.info(f'已设置{variable_scope}变量: {name} = {value_str}')
        set_info = f'操作: 已设置{variable_scope}【{name}】,值为: 【{value_str}】'
        allure_handler.add_step(step=set_info)

    @staticmethod
    def vars_replace(template: str | dict, env: str = None) -> Any:
        """
        替换模板中的变量占位符

        :param template: 包含变量占位符的模板字符串
        :return: 替换后的字符串
        """
        # 判断是否需要转换为字符串
        original_type = type(template)
        is_str = isinstance(template, str)

        # 如果不是字符串，尝试将其转换为字符串
        if not is_str:
            try:
                template = json.dumps(template)
            except (TypeError, ValueError) as e:
                raise ValueError(f"无法将输入转换为字符串: {e}")

        # 创建模板对象并进行变量替换
        template_obj = Template(template)
        try:
            result = template_obj.substitute(cache)
        except KeyError as e:
            log.error(f"未找到变量: {e}")
            result = template

        # 如果原始类型不是字符串，尝试将其还原为原始类型
        if not is_str:
            try:
                result = json.loads(result)
            except (TypeError, ValueError) as e:
                raise ValueError(f"无法将结果转换回原始类型: {e}")

        return result

    def relate_vars_replace(self, target: dict) -> dict:
        """
        关联变量替换

        :param target:
        :return:
        """
        pass

    def teardown_var_extract(self, response: dict, extract_model: ExtractVariableModel | str) -> None:
        """
        后置参数提取

        :param response:
        :param extract_model:
        :return:
        """

        # 记录变量提取的开始信息
        # log.info(f'执行变量提取：{extract["key"]}')

        # 提取变量名、类型和JSON路径
        # key = extract['key']
        # set_type = extract['type']

        # 调用记录变量的方法，将提取的变量记录到环境中
        self.record_variables(target_obj=response, model=extract_model)


class VariableManager:
    """
    变量管理器，用于管理全局变量和临时变量
    """

    def __init__(self):
        self.global_vars = {}
        self.temp_vars = {}

    def get(self, key, scope="temporary"):
        """
        获取变量值

        :param key: 变量名称
        :param scope: 变量作用域，可选值包括"global"和"temporary"
        """
        if scope == "global":
            return self.global_vars.get(key)
        return self.temp_vars.get(key)

    def set(self, key, value, scope="temporary"):
        """
        设置变量值

        :param key: 变量名称
        :param value: 变量值
        :param scope: 变量作用域，可选值包括"global"和"temporary"
        """
        if scope == "global":
            self.global_vars[key] = value
        else:
            self.temp_vars[key] = value

    def clear_temp_vars(self):
        """清除临时变量"""

        self.temp_vars.clear()


var_extractor = VarsExtractor()
